//
//  ACPresentAnimationManager.swift
//  ACFrameworkSwift
//
//  Created by fisherman on 2021/12/16.
//

// TODO：增加更多的动画，以及更多的自定义属性
// - 下滑关闭
// - 关闭的回调
// - 多种动画，如左进右出、缩放等等

import Foundation

/**
 * 快捷管理 present vc 时的动画转场。特性：
 * - 简单方便聚合，只需设置一个 transitioningDelegate
 * - 支持定义呈现动画，视图大小等
 *
 * 示例：DemoBViewController.swift
 *  - 定义  var presentMgr = ACPresentAnimationManager()
 *  - 重写 init，关联代理 self.transitioningDelegate = presentMgr，并自定义 presentMgr 的相关属性
 *
 * 使用方直接正常调用 present B 即可
 */
public class ACPresentAnimationManager: NSObject {
    
    /// 呈现内容的大小，超出范围则默认展示的是带透明的的背景
    var presentSize: CGSize
    /// 遮罩层颜色透明度，主色为黑色，自定义透明度
    var maskColorAlpha: CGFloat
    /// true：点击遮罩层视图自动关闭
    var enableTapMaskAutoClose: Bool
    
    public init(presentSize: CGSize = .zero, maskColorAlpha: CGFloat = 0.4, enableTapMaskAutoClose: Bool = false) {
        self.presentSize = presentSize
        self.maskColorAlpha = maskColorAlpha
        self.enableTapMaskAutoClose = enableTapMaskAutoClose
        super.init()
    }
}

// MARK: - UIViewControllerTransitioningDelegate

extension ACPresentAnimationManager: UIViewControllerTransitioningDelegate {
    
    public func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
        return ACPresentController(presentedViewController: presented, presenting: presenting, presentSize: presentSize, maskColorAlpha: maskColorAlpha)
    }
    
    public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return ACPresentAnimator()
    }
    
    public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return ACPresentAnimator(isPresent: false)
    }
}


/**
 * 自定义的呈现动画
 */
class ACPresentAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    
    /// true-present，false-dismiss
    var isPresent: Bool
    
    init(isPresent: Bool = true) {
        self.isPresent = isPresent
        super.init()
    }
    
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.3
    }
    
    // 自定义呈现与消失的转场动画
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        
        // present: A -> B, fromVc = A, toVc = B
        // dismiss: B -> A, fromVc = B, toVc = A
        
        guard let fromVc = transitionContext.viewController(forKey: .from),
              let toVc = transitionContext.viewController(forKey: .to) else {
                  return
              }
        let containerView = transitionContext.containerView
        let bounds = containerView.bounds
        
        if isPresent {
            let finalFrame = transitionContext.finalFrame(for: toVc)
            let initialFrame = finalFrame.offsetBy(dx: 0, dy: -bounds.height)
            
            toVc.view.frame = initialFrame
            containerView.addSubview(toVc.view)
            
            UIView.animate(withDuration: transitionDuration(using: transitionContext)) {
                fromVc.view.alpha = 0.5
                toVc.view.frame = finalFrame
            } completion: {_ in
                transitionContext.completeTransition(true)
                fromVc.view.alpha = 1.0
            }
        }else {
            let initialFrame = transitionContext.finalFrame(for: fromVc)
            let finalFrame = initialFrame.offsetBy(dx: 0, dy: bounds.height)
            fromVc.view.frame = initialFrame
            
            UIView.animate(withDuration: transitionDuration(using: transitionContext)) {
                toVc.view.alpha = 0.5
                fromVc.view.frame = finalFrame
            } completion: {_ in
                transitionContext.completeTransition(true)
                toVc.view.alpha = 1.0
            }
        }
    }
}


/**
 * 自定义的呈现视图，会自动在最底层添加一层遮罩
 */
class ACPresentController: UIPresentationController {
    /// 呈现视图大小
    private var presentSize: CGSize
    /// 遮罩层颜色透明度，主色为黑色，自定义透明度
    private var maskColorAlpha: CGFloat
    
    /// 遮罩层
    private lazy var maskView: UIView = {
        let mask = UIView()
        mask.alpha = 0.0
        return mask
    }()
    
    init(presentedViewController: UIViewController, presenting: UIViewController?, presentSize: CGSize, maskColorAlpha: CGFloat) {
        self.presentSize = presentSize
        self.maskColorAlpha = maskColorAlpha
        super.init(presentedViewController: presentedViewController, presenting: presenting)
    }
    
    // 设置呈现视图的大小
    override var frameOfPresentedViewInContainerView: CGRect {
        let windowSize = UIScreen.main.bounds.size
        var frame = CGRect.zero
        
        let width = containerView?.frame.width ?? windowSize.width
        let height = containerView?.frame.height ?? windowSize.height
        
        frame.size = presentSize
        frame.origin = CGPoint(x: (width - presentSize.width) * 0.5, y: (height - presentSize.height) * 0.5)
        
        return frame
    }
    
    // presentationTransitionWillBegin 是在呈现过渡即将开始的时候被调用的。在此添加遮罩层
    override func presentationTransitionWillBegin() {
        guard let `containerView` = containerView else { return }
        
        maskView.backgroundColor = UIColor.black.withAlphaComponent(maskColorAlpha)
        maskView.frame = containerView.bounds
        containerView.insertSubview(maskView, at: 0)
        
        guard let coordinator = presentedViewController.transitionCoordinator else {
            self.maskView.alpha = 1.0
            return
        }
        coordinator.animate { _ in
            self.maskView.alpha = 1.0
        }
    }
    
    //presentationTransitionDidEnd: 是在呈现过渡结束时被调用的，并且该方法提供一个布尔变量来判断过渡效果是否完成
    override func presentationTransitionDidEnd(_ completed: Bool) {
        if completed == false {
            maskView.removeFromSuperview()
        }
    }
    
    override func dismissalTransitionWillBegin() {
        guard let coordinator = presentedViewController.transitionCoordinator else {
            self.maskView.alpha = 0.0
            return
        }
        coordinator.animate { _ in
            self.maskView.alpha = 0.0
        }
    }
    
    override func dismissalTransitionDidEnd(_ completed: Bool) {
        if completed {
            maskView.removeFromSuperview()
        }
    }
}
